using System;
using System.Configuration;
using System.Net.Mail;
using System.Xml;

using log4net;

/*	-----------------------------------------------------------------------	
	Copyright:	umlungu consulting (Pty) ltd
	Author:		Alan Benington	
	Started:	2005-05-15	
	Status:		release	
	Version:	2.0.0
	Buidl:		20070524
	License:	GNU General Public License
	-----------------------------------------------------------------------	*/

/*	-----------------------------------------------------------------------	
	Development Notes:
	==================
	20070524:	Modification for .Net 2.0
	20071204:	Added some safety to getBlogListXml
	-----------------------------------------------------------------------	*/

namespace umlungu.engineX.webX.thoughts.Admin {
	/// <summary>
	/// umlungu engineX web framework, xxx class.
	/// </summary>
	public class Handlers
	{
		static string defaultBlogType = "html";
		private static ILog logger;


		#region Public methods
		/// <summary>Constructor</summary>
		public Handlers() {
			logger = LogManager.GetLogger(typeof(Handlers));
			log4net.Config.XmlConfigurator.Configure();
		}
		#endregion

		#region Default service delegates
		public static void processFormNoAction(profileX profile, contentX content)							{	}
		public static void processServiceNoAction(XmlDocument xmldom, profileX profile, contentX content)	{	}
		#endregion

		#region Login service delegates
		/// <summary>
		/// Method description
		/// </summary>
		public static void processLogin(XmlDocument xmldom, profileX profile, contentX content) 			{	getLoginXml(xmldom, profile);	}
		#endregion

		#region User Service delegates 
		public static void processUserList(XmlDocument xmldom, profileX profile, contentX content)			{	getUserListXml(xmldom, profile, content, "");	}
		public static void processUserGet(XmlDocument xmldom, profileX profile, contentX content)			{	setUserProfile(profile);	}
		public static void processUserAdd(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processUserEdit(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processUserProfileEdit(XmlDocument xmldom, profileX profile, contentX content)	{	setUserXml(xmldom, profile);	}
		public static void processUserDelete(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processUserGetAdd(XmlDocument xmldom, profileX profile, contentX content)		{	getUserDropXml(xmldom, profile, content);	}
		public static void processUserGetEdit(XmlDocument xmldom, profileX profile, contentX content)		{	getUserXml(xmldom, profile);	}
		public static void processUserGetDel(XmlDocument xmldom, profileX profile, contentX content)		{	getUserXml(xmldom, profile);	}
		public static void processUserGetBlog(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processUserAddBlog(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processUserChangeLogin(XmlDocument xmldom, profileX profile, contentX content)	{	}
		public static void processUserGetSpacesID(XmlDocument xmldom, profileX profile, contentX content)	{	getUserXml(xmldom, profile);	getUserSpacesXml(xmldom, profile, content);	setUserID(profile);	}
		public static void processUserGetSpaces(XmlDocument xmldom, profileX profile, contentX content)		{	getUserXml(xmldom, profile);	getUserSpacesXml(xmldom, profile, content);	}
		public static void processUserGetAddSpace(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogspaceDropXml(xmldom, profile, content);	}
		public static void processUserAddSpace(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processUserDeleteSpace(XmlDocument xmldom, profileX profile, contentX content)	{	}
		public static void processUserDefaultSpace(XmlDocument xmldom, profileX profile, contentX content)	{	}
		#endregion

		#region Author Service delegates 
		public static void processAuthorList(XmlDocument xmldom, profileX profile, contentX content)		{	getUserListXml(xmldom, profile, content, "author");	}
		public static void processAuthorAdd(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processAuthorEdit(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processAuthorDelete(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processAuthorGetBlog(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processAuthorAddBlog(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processAuthorGetAdd(XmlDocument xmldom, profileX profile, contentX content)		{	getUserDropXml(xmldom, profile, content);	}
		public static void processAuthorGetEdit(XmlDocument xmldom, profileX profile, contentX content)		{	getUserXml(xmldom, profile);	}
		public static void processAuthorGetDel(XmlDocument xmldom, profileX profile, contentX content)		{	getUserXml(xmldom, profile);	}
		#endregion

		#region Subscriber Service delegates 
		public static void processSubscriberList(XmlDocument xmldom, profileX profile, contentX content)		{	getUserListXml(xmldom, profile, content, "public");	}
		public static void processSubscriberAdd(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processSubscriberEdit(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processSubscriberDelete(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processSubscriberGetAdd(XmlDocument xmldom, profileX profile, contentX content)		{	getUserDropXml(xmldom, profile, content);	}
		public static void processSubscriberGetEdit(XmlDocument xmldom, profileX profile, contentX content)		{	getUserXml(xmldom, profile);	}
		public static void processSubscriberGetDel(XmlDocument xmldom, profileX profile, contentX content)		{	getUserXml(xmldom, profile);	}
		#endregion

		#region Topic Service delegates 
		public static void processTopicList(XmlDocument xmldom, profileX profile, contentX content)			{	getTopicListXml(xmldom, profile, content);	}
		public static void processTopicAdd(XmlDocument xmldom, profileX profile, contentX content)			{	addTopics(xmldom, profile);	}
		public static void processTopicEdit(XmlDocument xmldom, profileX profile, contentX content)			{	addTopics(xmldom, profile);	}
		public static void processTopicDelete(XmlDocument xmldom, profileX profile, contentX content)		{	addTopics(xmldom, profile);	}
		public static void processTopicGetBlog(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processTopicAddBlog(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processTopicGetAdd(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processTopicGetEdit(XmlDocument xmldom, profileX profile, contentX content)		{	getTopicXml(xmldom, profile);	}
		public static void processTopicGetDel(XmlDocument xmldom, profileX profile, contentX content)		{	getTopicXml(xmldom, profile);	}
		public static void processTopicAddImage(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processTopicUpdate(XmlDocument xmldom, profileX profile, contentX content)		{	addTopics(xmldom, profile);	}
		#endregion

		#region Link Service delegates 
		public static void processLinkList(XmlDocument xmldom, profileX profile, contentX content)			{	getLinkListXml(xmldom, profile, content);	}
		public static void processLinkAdd(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processLinkEdit(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processLinkDelete(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processLinkGetAdd(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processLinkGetEdit(XmlDocument xmldom, profileX profile, contentX content)		{	getLinkXml(xmldom, profile);	}
		public static void processLinkGetDel(XmlDocument xmldom, profileX profile, contentX content)		{	getLinkXml(xmldom, profile);	}
		#endregion

		#region Blog Service delegates 
		public static void processGetBlogListCust(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogListXml(xmldom, profile, content, false);	}
		public static void processGetBlogListCustDef(XmlDocument xmldom, profileX profile, contentX content){	getBlogListXml(xmldom, profile, content, true);		}
		public static void processGetBlogList(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogListXml(xmldom, profile, content, false);	}
		public static void processGetBlogListDef(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogListXml(xmldom, profile, content, true);		}
		public static void processGetBlogListAll(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogListXml(xmldom, profile, content, true);		}
		public static void processAdd(XmlDocument xmldom, profileX profile, contentX content)				{	}
		public static void processAddHtml(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processAddText(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processAddImage(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processEdit(XmlDocument xmldom, profileX profile, contentX content)				{	}
		public static void processEditHtml(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processEditText(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processDelete(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processGetBlogView(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processGetBlogEdit(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile);	}
		public static void processGetBlogEditCustom(XmlDocument xmldom, profileX profile, contentX content) {	getBlogXml(xmldom, profile, true, false); }
		public static void processGetBlogDel(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile); }
		public static void processGetBlogDelCustom(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogXml(xmldom, profile, true, false); }
		public static void processGetBlogDateEdit(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogDateXml(xmldom, profile); }
		public static void processGetBlogDateDel(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogDateXml(xmldom, profile);	}
		public static void processGetBlog(XmlDocument xmldom, profileX profile, contentX content)			{	getBlogXml(xmldom, profile);	}
		// new method for generic editing of blogs
		public static void processGetBlogEditAll(XmlDocument xmldom, profileX profile, contentX content) { getBlogXml(xmldom, profile, content); }
		#endregion

		#region Blog-Comment Service delegates
		public static void processGetBlogComment(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogXml(xmldom, profile); }
		public static void processGetCommentEdit(XmlDocument xmldom, profileX profile, contentX content)	{	getCommentXml(xmldom, profile);	}
		public static void processGetCommentDel(XmlDocument xmldom, profileX profile, contentX content)		{	getCommentXml(xmldom, profile);	}
		public static void processAddComment(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processEditComment(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processDeleteComment(XmlDocument xmldom, profileX profile, contentX content)		{	}
		#endregion

		#region Blog-Image Service delegates
		public static void processGetBlogImage(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogXml(xmldom, profile); }
		public static void processGetBlogImageEdit(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogImageXml(xmldom, profile); }
		public static void processGetBlogImageDel(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogImageXml(xmldom, profile); }
		public static void processAddBlogImage(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogImageID(xmldom, profile); }
		public static void processEditBlogImage(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processDeleteBlogImage(XmlDocument xmldom, profileX profile, contentX content)	{	}
		public static void processDefaultBlogImage(XmlDocument xmldom, profileX profile, contentX content)	{	}
		#endregion

		#region BlogSpace Service delegates 
		public static void processGetBlogspaceList(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogspaceListXml(xmldom, profile, content);	}
		public static void processAddSpace(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processDeleteSpace(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processEditSpace(XmlDocument xmldom, profileX profile, contentX content)			{	}
		public static void processUpdateSpace(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processGetBlogspace(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogspaceXml(xmldom, profile);		}
		public static void processSetBlogspace(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogspaceXml(xmldom, profile);	blogspaceSet(profile);	}
		public static void processGetBlogspaceArch(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogspaceArchive(xmldom, profile);	}
		public static void processGetBlogspaceDel(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogspaceXml(xmldom, profile);		}
		public static void processGetBlogspaceEdit(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogspaceXml(xmldom, profile);		}
		public static void processGetBlogspaceView(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogspaceXml(xmldom, profile);		}
		public static void processGetBlogspaceBlog(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogXml(xmldom, profile);			}
		public static void processGetBlogspaceImage(XmlDocument xmldom, profileX profile, contentX content)	{	getBlogXml(xmldom, profile);			}
		public static void processAddBlogspaceImage(XmlDocument xmldom, profileX profile, contentX content)	{	}
		public static void processChangeArchive(XmlDocument xmldom, profileX profile, contentX content)		{	getBlogspaceArchive(xmldom, profile);	}
		public static void processUploadNews(XmlDocument xmldom, profileX profile, contentX content)		{	}
		public static void processSendNews(XmlDocument xmldom, profileX profile, contentX content)			{	}
		#endregion

		#region Form delegates
		public static void processBlogAdd(profileX profile, contentX content)								{	blogReset(profile);			}
		public static void processLogout(profileX profile, contentX content)								{	profile.Reset();			}
		public static void processAuthorAdd(profileX profile, contentX content)								{	authorReset(profile);		}
		public static void processSubscriberAdd(profileX profile, contentX content)							{	subscriberReset(profile);		}
		public static void processTopicAdd(profileX profile, contentX content)								{	topicReset(profile);		}
		public static void processLinkAdd(profileX profile, contentX content)								{	linkReset(profile);			}
		public static void processUserAdd(profileX profile, contentX content)								{	authorReset(profile);		}
		public static void processBlogspaceAdd(profileX profile, contentX content)							{	blogspaceReset(profile);	}
		public static void processBlogspaceSet(profileX profile, contentX content)							{	blogspaceSet(profile);		}
		#endregion

		#region Contact Form delegates
		public static void processContactPassword(profileX profile, contentX content)						{	sendContact(profile, "Password");	}
		public static void processContactGeneral(profileX profile, contentX content)						{	sendContact(profile, "General");	}
		#endregion

		#region Protected methods
		/// <summary>
		/// Method description
		/// </summary>
		protected void _Method() {
		}
		#endregion

		#region Private methods
		/// <summary>
		/// Method description
		/// </summary>
		private static void blogReset(profileX profile) {
			profile.AddProfileValue("BlogID", "0");
			profile.ClearProfileValue("Title");
			profile.ClearProfileValue("Intro");
			profile.ClearProfileValue("Text");
			profile.ClearProfileValue("Comment_Text");
			profile.ClearProfileValue("Comment_Title");
		}
		/// <summary>
		/// addTopics:: Add topics to profile field (for topic filter)
		/// </summary>
		private static void addTopics(XmlDocument xmldom, profileX profile) {
			addTopics(xmldom, profile, true);
		}
		private static void addTopics(XmlDocument xmldom, profileX profile, bool wantdefault) {
			XmlNode topicsnode = xmldom.SelectSingleNode("//topics");
			if (topicsnode != null) {
				profile.ClearSubobjfromFld("Topics");
				profile.AddSubobjtoFld("Topics", "All sections", (wantdefault)? "*" : "*,-default");
				XmlElement nodeElem;
				foreach (XmlNode node in topicsnode.SelectNodes("topic")) {
					nodeElem = (XmlElement) node;
					if (!wantdefault && nodeElem.GetAttribute("name") == "default")
						continue;
					string label = (node.SelectSingleNode("blog")!=null)? nodeElem.LastChild.InnerText : nodeElem.InnerText;
					profile.AddSubobjtoFld("Topics", label, nodeElem.GetAttribute("name"));
				}
			}
		}
		#endregion

		#region Login methods
		/// <summary>
		/// getLoginXml:: Called by Login service delegate
		/// </summary>
		private static void getLoginXml(XmlDocument xmldom, profileX profile) {
			setUserXml(xmldom, profile);
			addSpaces(xmldom, profile);
			addTopics(xmldom, profile);
			addAuthors(xmldom, profile);
			setSpaceType(xmldom, profile);
		}
		/// <summary>
		/// addIdentity:: Add user identity information to profile
		/// </summary>
		private static void addIdentity(profileX profile, string token, string group, string username, string firstname, string surname, string email, string telno) {
			profile.Token = token;
			profile.Group = group;
			profile.Username = username;
			profile.Firstname = firstname;
			profile.Surname = surname;
			profile.Name = String.Concat(firstname, " ", surname);
			profile.Email = email;
			profile.Telno = telno;
			// Now add values to profile: required for pre-pop forms
			// - replace the pre-pop mechanism to get from profile (Identity) object directly
			setUserProfile(profile);
		}
		/// <summary>
		/// setUserProfile:: (re)set user profile values from profile
		/// </summary>
		private static void setUserProfile(profileX profile) {
			profile.AddProfileValue("Username", profile.Username);
			profile.AddProfileValue("Firstname", profile.Firstname);
			profile.AddProfileValue("Surname", profile.Surname);
			profile.AddProfileValue("Name", profile.Name);
			profile.AddProfileValue("Email", profile.Email);
			profile.AddProfileValue("Telno", profile.Telno);
		}
		/// <summary>
		/// addSpaces:: Add blogspaces to profile field (for blogspace filter)
		/// </summary>
		private static void addSpaces(XmlDocument xmldom, profileX profile) {
			XmlElement spacesnode = (XmlElement) xmldom.SelectSingleNode("//user/blogspaces");
			if (spacesnode != null) {
				XmlElement nodeElem;
				profile.ClearSubobjfromFld("BlogSpaces");
				foreach (XmlNode node in spacesnode.SelectNodes("blogspace")) {
					nodeElem = (XmlElement) node;
					profile.AddSubobjtoFld("BlogSpaces", nodeElem.FirstChild.InnerText, nodeElem.GetAttribute("name"));
				}
				profile.AddProfileValue("BlogSpaces", spacesnode.GetAttribute("default"));
			}
		}
		/// <summary>
		/// addAuthors:: Add authors to profile field (for authors filter)
		/// </summary>
		private static void addAuthors(XmlDocument xmldom, profileX profile) {
			XmlNode authorsnode = xmldom.SelectSingleNode("//blogspace/users");
			if (authorsnode != null) {
				profile.ClearSubobjfromFld("Authors");
				profile.AddSubobjtoFld("Authors", "Show all pages", "0");
				XmlElement nodeElem;
				foreach (XmlNode node in authorsnode.SelectNodes("user")) {
					nodeElem = (XmlElement) node;
					string fullname = String.Concat(nodeElem.SelectSingleNode("firstname").InnerText, " ", nodeElem.SelectSingleNode("surname").InnerText);
					//string prompt = String.Concat("Show only ", nodeElem.SelectSingleNode("firstname").InnerText, "'s posts");
					string prompt = String.Concat("Only ", nodeElem.SelectSingleNode("firstname").InnerText, "'s pages");
					profile.AddSubobjtoFld("Authors", prompt, fullname);
				}
			}
			profile.AddProfileValue("Authors", "0");
		}
		/// <summary>
		/// setSpaceType:: Set the default blog format for blogspace
		/// </summary>
		private static void setSpaceType(XmlDocument xmldom, profileX profile) {
			XmlElement spacesel = (XmlElement) xmldom.SelectSingleNode("//blogspaces");
			if (spacesel != null) {
				XmlElement spaceel = (XmlElement) spacesel.SelectSingleNode(String.Concat("blogspace[@name='", spacesel.GetAttribute("default"),"']"));
				if (spaceel != null) {
					string thistype = (spaceel.GetAttribute("type") == "")? defaultBlogType : spaceel.GetAttribute("type");
					profile.AddProfileValue("SpaceType", thistype);
				} else {
					profile.AddProfileValue("SpaceType", defaultBlogType);
				}
			}
		}
		#endregion

		#region User methods
		private static void getUserSpacesXml(XmlDocument xmldom, profileX profile, contentX content) {
			// add blogspaces to profile items
			XmlElement spacesnode = (XmlElement) xmldom.SelectSingleNode("//blogspaces");
			string spacedef = spacesnode.GetAttribute("default");
			XmlNode itemsnode = content.Xml.SelectSingleNode("//page/section/grpform/items");
			if (spacesnode != null) {
				XmlNodeList nodeList = spacesnode.SelectNodes("blogspace");
				foreach (XmlNode node in nodeList) {
					XmlElement nodeElem = (XmlElement) node;
					XmlElement itemnode = xmlX.AddElemAttrNode(content.Xml, node, "item", 3);
					itemnode.SetAttribute("default", (nodeElem.GetAttribute("name") == spacedef)? "yes" : "no");
					itemsnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)
					xmlX.AddElemAttr(content.Xml, itemsnode, "nodata", "", "prompt", "no thoughtspaces");
			}
		}
		private static void setUserID(profileX profile) {
			// add user (id) to profile as "Username"
			profile.AddProfileValue("Username", profile.GetProfileValue("id"));
		}
		#endregion

		#region Author methods
		private static void setUserXml(XmlDocument xmldom, profileX profile) {
			XmlElement usrnode = (XmlElement) xmldom.SelectSingleNode("//user");
			if (usrnode != null) {
				addIdentity(profile,
							usrnode.GetAttribute("token"),
							usrnode.GetAttribute("group"),
							usrnode.GetAttribute("name"),
							usrnode.SelectSingleNode("firstname").InnerText,
							usrnode.SelectSingleNode("surname").InnerText,
							usrnode.SelectSingleNode("email").InnerText,
							usrnode.SelectSingleNode("telno").InnerText);
			}
		}
		private static void getUserXml(XmlDocument xmldom, profileX profile) {
			// add user details to profile items
			XmlElement userelem = (XmlElement) xmldom.SelectSingleNode("//user");
			if (userelem != null) {
				profile.AddProfileValue("Group", userelem.GetAttribute("group"));
				profile.AddProfileValue("Username", userelem.GetAttribute("name"));
				profile.AddProfileValue("Firstname", userelem.SelectSingleNode("firstname").InnerText);
				profile.AddProfileValue("Surname", userelem.SelectSingleNode("surname").InnerText);
				profile.AddProfileValue("Email", userelem.SelectSingleNode("email").InnerText);
				profile.AddProfileValue("Telno", userelem.SelectSingleNode("telno").InnerText);
				profile.AddProfileValue("Field1", (userelem.SelectSingleNode("field1")!= null)? userelem.SelectSingleNode("field1").InnerText : "");
				profile.AddProfileValue("Field2", (userelem.SelectSingleNode("field2")!= null)? userelem.SelectSingleNode("field2").InnerText : "");
				profile.AddProfileValue("Field3", (userelem.SelectSingleNode("field3")!= null)? userelem.SelectSingleNode("field3").InnerText : "");
				profile.AddProfileValue("Field4", (userelem.SelectSingleNode("field4")!= null)? userelem.SelectSingleNode("field4").InnerText : "");
			}
		}
		private static void getUserListXml(XmlDocument xmldom, profileX profile, contentX content, string which) {
			// add users to profile items
			XmlNode usersnode = xmldom.SelectSingleNode("//users");
			XmlNode itemsnode = content.Xml.SelectSingleNode("//page/section/grpform/items");
			if (usersnode != null) {
				XmlNodeList nodeList = usersnode.SelectNodes((which == "")? "user" : String.Concat("user[@group='", which, "']"));
				foreach (XmlNode node in nodeList) {
					XmlElement nodeElem = (XmlElement) node;
					XmlElement itemnode = xmlX.AddElemAttrNode(content.Xml, node, "item", 3);
					itemsnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)
					xmlX.AddElemAttr(content.Xml, itemsnode, "nodata", "", "prompt", "no users");
			}
		}
		// add users to a drop-down fld on the content page (result of search for user/author)
		private static void getUserDropXml(XmlDocument xmldom, profileX profile, contentX content) {
			XmlNode usersnode = xmldom.SelectSingleNode("//users");
			XmlNode fldnode = content.Xml.SelectSingleNode("//page/section/fields/fld[@name='Username']");
			if (usersnode != null) {
				XmlElement subsnode = (XmlElement) xmlX.AddElem(content.Xml, fldnode, "subobjs", "");
				XmlElement subnode = (XmlElement) xmlX.AddElem(content.Xml, subsnode, "subwf_obj", "");
				xmlX.AddElem(content.Xml, subnode, "value", "0");
				xmlX.AddElem(content.Xml, subnode, "prompt", "Select user...");
				XmlNodeList nodeList = usersnode.SelectNodes("user");
				foreach (XmlNode node in nodeList) {
					XmlElement userelem = (XmlElement) node;
					subnode = (XmlElement) xmlX.AddElem(content.Xml, subsnode, "subwf_obj", "");
					xmlX.AddElem(content.Xml, subnode, "value", userelem.GetAttribute("name"));
					xmlX.AddElem(content.Xml, subnode, "prompt", String.Concat(userelem.SelectSingleNode("firstname").InnerText, " ", userelem.SelectSingleNode("surname").InnerText));
				}
			}
		}
		private static void authorReset(profileX profile) {
			profile.ClearProfileValue("Username");
			profile.ClearProfileValue("Firstname");
			profile.ClearProfileValue("Surname");
			profile.ClearProfileValue("Email");
			profile.ClearProfileValue("Telno");
			profile.ClearProfileValue("Group");
			profile.ClearProfileValue("Secret");
			profile.ClearProfileValue("Password");
		}
		private static void subscriberReset(profileX profile) {
			profile.ClearProfileValue("Username");
			profile.ClearProfileValue("Firstname");
			profile.ClearProfileValue("Surname");
			profile.ClearProfileValue("Email");
			profile.ClearProfileValue("Telno");
			profile.ClearProfileValue("Group");
		}
		private static void topicReset(profileX profile) {
			profile.ClearProfileValue("Topic");
			profile.ClearProfileValue("Title");
		}
		private static void linkReset(profileX profile) {
			profile.ClearProfileValue("Text");
			profile.ClearProfileValue("Url");
			profile.ClearProfileValue("id");
		}
		#endregion

		#region Topic methods
		private static void addTopicsListXml(XmlDocument xmldom, profileX profile) {
			// add topics to profile items
			XmlNode topicsnode = xmldom.SelectSingleNode("//topics");
			if (topicsnode != null) {
				XmlNodeList nodeList = topicsnode.SelectNodes("topic");
				foreach (XmlNode node in nodeList) {
					XmlNode itemnode = xmlX.AddElemAttrNode(xmldom, node, "item", 1);
					itemnode.InnerText = node.InnerText;	// can contain ' and " etc
					topicsnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)	// add nodata element when no results
					xmlX.AddElemAttr(xmldom, topicsnode, "nodata", "", "prompt", "no topics");
				profile.AddNodetoProfile("profile", topicsnode, true);
			}
		}
		private static void getTopicListXml(XmlDocument xmldom, profileX profile, contentX content) {
			// add users to profile items
			XmlNode topicsnode = xmldom.SelectSingleNode("//topics");
			XmlNode itemsnode = content.Xml.SelectSingleNode("//page/section/grpform/items");
			if (topicsnode != null) {
				XmlNodeList nodeList = topicsnode.SelectNodes("topic");
				foreach (XmlNode node in nodeList) {
					XmlElement nodeElem = (XmlElement) node;
					XmlElement itemnode = xmlX.AddElemAttrNode(content.Xml, node, "item", 3);
					XmlNode imgnode = node.SelectSingleNode("blog/image");
					itemnode.SetAttribute("image", (imgnode == null)? " - " : imgnode.InnerText);
					XmlNode blognode = node.SelectSingleNode("blog");
					itemnode.SetAttribute("about", (blognode == null)? "no" : "yes");
					itemnode.SetAttribute("title", (blognode == null)? " - " : blognode.SelectSingleNode("title").InnerText);
					itemsnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)
					xmlX.AddElemAttr(content.Xml, itemsnode, "nodata", "", "prompt", "no topics");
			}
			getBlogspaceArchive(xmldom, profile);
		}
		private static void getTopicXml(XmlDocument xmldom, profileX profile) {
			// add topics to profile items
			string thisid = profile.GetProfileValue("id");
			XmlNode topicnode = xmldom.SelectSingleNode("//topics/topic[@name='"+thisid+"']");
			if (topicnode != null) {
				profile.AddProfileValue("Topic", thisid);
				XmlNode blognode = topicnode.SelectSingleNode("blog");
				profile.AddProfileValue("Label", (blognode != null)? topicnode.LastChild.InnerText : topicnode.InnerText);
				profile.AddProfileValue("Title", (blognode != null)? blognode.SelectSingleNode("title").InnerText : "");
				profile.AddProfileValue("Text", (blognode != null)? blognode.SelectSingleNode("bloghtml").InnerText : "");
				XmlNode imgnode = topicnode.SelectSingleNode("blog/image");
				profile.AddProfileValue("ImageName", (imgnode != null)? imgnode.InnerText : "");
			}
		}
		#endregion

		#region Link methods
		private static void getLinkListXml(XmlDocument xmldom, profileX profile, contentX content) {
			// add users to profile items
			XmlNode linksnode = xmldom.SelectSingleNode("//links");
			XmlNode itemsnode = content.Xml.SelectSingleNode("//page/section/grpform/items");
			if (linksnode != null) {
				XmlNodeList nodeList = linksnode.SelectNodes("link");
				foreach (XmlNode node in nodeList) {
					XmlElement nodeElem = (XmlElement) node;
					XmlElement itemnode = xmlX.AddElemAttrNode(content.Xml, node, "item", 3);
					itemsnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)
					xmlX.AddElemAttr(content.Xml, itemsnode, "nodata", "", "prompt", "no links");
			}
		}
		private static void getLinkXml(XmlDocument xmldom, profileX profile) {
			// add links to profile items
			string thisid = profile.GetProfileValue("id");
			XmlElement linkelem = (XmlElement) xmldom.SelectSingleNode("//links/link[@id='"+thisid+"']");
			if (linkelem != null) {
				profile.AddProfileValue("id", thisid);
				profile.AddProfileValue("Text", linkelem.InnerText);
				profile.AddProfileValue("Url", linkelem.GetAttribute("url"));
			}
		}
		#endregion

		#region Blog methods
		private static void getBlogListXml(XmlDocument xmldom, profileX profile, contentX content, bool wantDefault) {
			setSpaceType(xmldom, profile);
			// add blogs to profile items
			XmlElement blogsnode = (XmlElement) xmldom.SelectSingleNode("//blogs");
			XmlNode itemsnode = content.Xml.SelectSingleNode("//page/section/grpform/items");
			if (blogsnode != null) {
				string type, blogstopic = blogsnode.GetAttribute("topic");
				XmlNodeList nodeList = blogsnode.SelectNodes("//blogs/blog");
				foreach (XmlNode node in nodeList) {
					XmlElement nodeElem = (XmlElement) node;
					if (node.SelectSingleNode("bloghtml") != null)
						type = "html";
					else if (node.SelectSingleNode("blogtext") != null)
						type = "text";
					else 
						type = "xml";
					//XmlElement textnode = (XmlElement) node.SelectSingleNode("text");
					//string type = (textnode == null)? "xml" : (textnode.GetAttribute("html") == "yes" || textnode.GetAttribute("type") == "html")? "html" : "text";	// older versions had html="yes"

					XmlElement itemnode = xmlX.AddElemAttrNode(content.Xml, node, "item", 1);
					if (!wantDefault && itemnode.GetAttribute("topic") == "default")
						continue;
					itemnode.SetAttribute("type", type);
					itemnode.SetAttribute("title", (node.SelectSingleNode("title") == null)? "" : node.SelectSingleNode("title").InnerText);
					string authname = (node.SelectSingleNode("author") == null)? "" : node.SelectSingleNode("author").InnerText;
					itemnode.SetAttribute("authorname", authname);
					if (itemnode.GetAttribute("initials") == "")
						itemnode.SetAttribute("initials", String.Concat(authname.Substring(0, 1), authname.Substring(authname.IndexOf(" ")+1, 1)));
					//if (itemnode.GetAttribute("topic") == "")
					//	itemnode.SetAttribute("topic", blogstopic);
					itemnode.SetAttribute("topic", ((XmlElement)nodeElem.ParentNode).GetAttribute("topic"));
					XmlNodeList commlst = node.SelectNodes("comments/comment");
					int commcnt = (commlst != null)? commlst.Count : 0;
					itemnode.SetAttribute("comments", commcnt.ToString());
					itemsnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)
					xmlX.AddElemAttr(content.Xml, itemsnode, "nodata", "", "prompt", "no posts - click 'Add' to add a new one");
			}
			addTopics(xmldom, profile, wantDefault);
			addArchives(xmldom, profile, blogsnode);
		}
		/// <summary>
		/// addArchives:: Add archives to profile field (for archive filter)
		/// </summary>
		private static void addArchives(XmlDocument xmldom, profileX profile, XmlNode defnode) {
			XmlElement defelem = (XmlElement) defnode;
			XmlNode archsnode;
			if (defelem != null)
				archsnode = xmldom.SelectSingleNode(String.Concat("//archives/topic[@name='", defelem.GetAttribute("topic"), "']"));
			else
				archsnode = xmldom.SelectSingleNode("//archives");
			// add archive list to profile
			profile.ClearSubobjfromFld("Archives");
			profile.AddSubobjtoFld("Archives", "Current posts", "0");
			if (archsnode != null) {
				XmlElement nodeElem;
				foreach (XmlNode node in archsnode.SelectNodes("archive")) {
					nodeElem = (XmlElement) node;
					//profile.AddSubobjtoFld("Archives", String.Concat("Show ", nodeElem.InnerText), nodeElem.GetAttribute("name"));
					profile.AddSubobjtoFld("Archives", String.Concat(nodeElem.InnerText), nodeElem.GetAttribute("name"));
				}
			}
		}
		/// <summary>
		/// getBlogXmlAll:: Add blog to profile fields
		//	Get blog for generic editing
		/// </summary>
		private static void getBlogXml(XmlDocument xmldom, profileX profile, contentX content) {
			XmlElement blognode = (XmlElement) xmldom.SelectSingleNode("//blog");
			XmlElement fldnode;
			string value;
			if (blognode != null) {
				foreach (XmlNode blgnode in blognode.ChildNodes) {
					fldnode = null;
					value = "";
					switch (blgnode.Name) {
						case "id":			fldnode = (XmlElement)content.Xml.SelectSingleNode("//fld[@name='id']");
											value = blgnode.InnerText;
											break;
						case "title":		fldnode = (XmlElement)content.Xml.SelectSingleNode("//fld[@name='Title']");
											value = blgnode.InnerXml;
											break;
						case "date":		if (blgnode.NodeType == XmlNodeType.Element) {
												fldnode = (XmlElement)content.Xml.SelectSingleNode("//fld[@name='Date']");
												value = blgnode.InnerXml;
											}
											break;
						case "blogtext":	fldnode = (XmlElement)content.Xml.SelectSingleNode("//fld[@name='Intro']");
											value = blgnode.InnerXml;
											break;
						case "bloghtml":	fldnode = (XmlElement)content.Xml.SelectSingleNode("//fld[@name='Text']");
											value = blgnode.FirstChild.InnerText;
											break;
						case "image":		fldnode = (XmlElement)content.Xml.SelectSingleNode("//fld[@name='Image']");
											value = blgnode.InnerXml;
											break;
						case "text":		fldnode = (XmlElement)content.Xml.SelectSingleNode("//fld[@name='Text']");
											XmlElement blgel = (XmlElement)blgnode;
											if (blgel.GetAttribute("type") == "html")
												value = blgnode.FirstChild.InnerText;
											else
												value = blgnode.InnerXml;
											break;
						default:			fldnode = (XmlElement)content.Xml.SelectSingleNode(String.Concat("//fld[@name='", blgnode.Name, "']"));
											value = blgnode.InnerXml;
											break;
					}
					if (fldnode != null) {
						XmlElement valel = content.Xml.CreateElement("value");
						fldnode.AppendChild(valel).InnerText = value;
					}
				}
			}
			foreach(XmlNode fldnde in content.Xml.SelectNodes("//fld[not(value)]"))
				fldnde.ParentNode.RemoveChild(fldnde);
		}

		/// <summary>
		/// getBlogXmlAll:: Add blog to profile fields
		/// </summary>
		private static void getBlogXml(XmlDocument xmldom, profileX profile) {
			//logger.Debug("getBlogXml");
			getBlogXml(xmldom, profile, true, true);
		}
		/// <summary>
		/// getBlogXml:: Add blog to profile fields
		/// </summary>
		private static void getBlogXml(XmlDocument xmldom, profileX profile, bool wantProfile, bool isStandard) {
			XmlElement blognode = xmldom.SelectSingleNode("//blog") as XmlElement;
			if (blognode != null) {
				if (isStandard) {
					addBlogtoFields(blognode, profile, wantProfile);
				} else {
					addBlogtoCustomFields(blognode, profile);
				}
				addBlogListXml(xmldom, profile);
			}
		}

		/// <summary>
		/// Adds blog xml to fields defined by blog element names
		/// </summary>
		private static void addBlogtoCustomFields(XmlElement blognode, profileX profile) {
			string val = "", nme = "";
			foreach (XmlNode blgnode in blognode.ChildNodes) {
				switch (blgnode.Name) {
					case "id":
						nme = "ID";
						val = blgnode.InnerText;
						break;
					case "title":
						nme = "Title";
						val = blgnode.InnerXml;
						break;
					case "date":
						if (blgnode.NodeType == XmlNodeType.Element) {
							nme = "Date";
							val = blgnode.InnerXml;
						}
						break;
					case "blogtext":
						nme = "Intro";
						val = blgnode.InnerXml;
						break;
					case "bloghtml":
						nme = "Text";
						val = blgnode.FirstChild.InnerText;
						break;
					case "image":
						nme = "Image";
						val = blgnode.InnerXml;
						break;
					case "text":
						nme = "Text";
						if ((blgnode as XmlElement).GetAttribute("type") == "html")
							val = blgnode.FirstChild.InnerText;
						else
							val = blgnode.InnerXml;
						break;
					default:
						nme = blgnode.Name;
						if ((blgnode as XmlElement).GetAttribute("type") == "html")
							val = blgnode.FirstChild.InnerText;
						else
							val = blgnode.InnerXml;
						break;
				}
				profile.AddProfileValue(nme, val);
			}
			profile.AddProfileValue("BlogType", "custom");
		}

		/// <summary>
		/// Adds blog xml to standard fields
		/// </summary>
		private static void addBlogtoFields(XmlElement blognode, profileX profile, bool wantProfile) {
			string thisid = "", thistitle = "", thistext = "", thisimg = "";
			bool isXml = false;

			thisid = blognode.GetAttribute("id");
			thistitle = blognode.SelectSingleNode("title").InnerXml;
			XmlElement textnode = (XmlElement)blognode.SelectSingleNode("bloghtml");
			if (textnode != null) {
				thistext = textnode.FirstChild.InnerText;
			} else {
				textnode = (XmlElement)blognode.SelectSingleNode("blogtext");
				if (textnode != null) {
					thistext = textnode.InnerXml;
				} else {
					textnode = (XmlElement)blognode.SelectSingleNode("text");
					if (textnode != null) {
						thistext = textnode.InnerXml;
					} else {	// xml?
						isXml = true;
						// remove title
						blognode.RemoveChild(blognode.SelectSingleNode("title"));
						thistext = blognode.InnerXml;
					}
				}
			}
			// add image file name
			XmlNode imagenode = blognode.SelectSingleNode("image");
			if (imagenode != null) {
				thisimg = imagenode.InnerText;
			}

			// call the appropriate method to add fields to interface via profile or content object
			if (wantProfile)
				addBlogToProfile(profile, (textnode != null) ? textnode : blognode, thisid, thistitle, thistext, thisimg);
			else
				addBlogToContent(profile, (textnode != null) ? textnode : blognode, thisid, thistitle, thistext, thisimg);

			// if image override type set in setBlogType
			if (imagenode != null) {
				profile.AddProfileValue("BlogType", "image");
			} else if (isXml) {
				profile.AddProfileValue("BlogType", "xml");
			}
		}

		/// <summary>
		/// addBlogToProfile:: add blog data to profile fields
		//	Was originally all part of getBlogXml
		/// </summary>
		private static void addBlogToProfile(profileX profile, XmlElement textnode, string thisid, string thistitle, string thistext, string thisimg) {
			// also add as a profile node (for html display)...
			profile.AddNodetoProfile("profile", textnode, true);
			setBlogType(textnode, profile);
			if (thisid != "")
				profile.AddProfileValue("ID", thisid);
			profile.AddProfileValue("Title", thistitle);
			profile.AddProfileValue("Text", thistext);
			profile.AddProfileValue("ImageName", thisimg);
		}
		/// <summary>
		/// addBlogToContent:: add blog data into fields in the content xml
		/// </summary>
		private static void addBlogToContent(profileX profile, XmlElement textnode, string thisid, string thistitle, string thistext, string thisimg) {
			
		}
		/// <summary>
		/// getBlogDateXml:: copy of getBlogXml for use with Date blog (has additional text)
		/// </summary>
		private static void getBlogDateXml(XmlDocument xmldom, profileX profile) {
			XmlElement blognode = (XmlElement) xmldom.SelectSingleNode("//blog");
			string thisid = "", thistitle = "", thistext = "", thishtml = "", thisimg = "";
			if (blognode != null) {
				thisid = blognode.GetAttribute("id");
				thistitle = blognode.SelectSingleNode("title").InnerXml;
				thistext = blognode.SelectSingleNode("blogtext").InnerXml;
				thishtml = blognode.SelectSingleNode("bloghtml").FirstChild.InnerText;
				// add image file name
				XmlNode imagenode = blognode.SelectSingleNode("image");
				if (imagenode != null)
					thisimg = imagenode.InnerText;
			}
			if (thisid != "")
				profile.AddProfileValue("ID", thisid);
			profile.AddProfileValue("Title", thistitle);
			profile.AddProfileValue("Intro", thistext);
			profile.AddProfileValue("Text", thishtml);
			profile.AddProfileValue("ImageName", thisimg);

			addBlogListXml(xmldom, profile);
		}
		// Set the BlogType (for edit page)
		private static void setBlogType(XmlElement txtnode, profileX profile) {
			string thistype = "html";	// default if not specified by textnode (or absence of textnode means xml)
			if (txtnode != null) {
				if (txtnode.Name == "blogtext")
					thistype = "text";
				else if (txtnode.Name == "bloghtml")
					thistype = "html";
				else if (txtnode.Name == "bloghtml")
					thistype = "html";
				else
					thistype = (txtnode.GetAttribute("type")== "")? thistype : txtnode.GetAttribute("type");
			} else
				thistype = "xml";
			profile.AddProfileValue("BlogType", thistype);
		}
		// add blog item lists to profile (eg comment and image lists)
		private static void addBlogListXml(XmlDocument xmldom, profileX profile) {
			addBlogCommentXml(xmldom, profile);
			addBlogImageXml(xmldom, profile);
		}
		// add comments to profile items - for comment list interface
		private static void addBlogCommentXml(XmlDocument xmldom, profileX profile) {
			profile.RemoveNodefromProfile("comments");
			XmlNode commentsnode = xmldom.SelectSingleNode("//blog/comments");
			if (commentsnode != null) {
				XmlNodeList nodeList = commentsnode.SelectNodes("comment");
				foreach (XmlNode node in nodeList) {
					XmlElement itemnode = xmlX.AddElemAttrNode(xmldom, node, "item", 1);
					itemnode.SetAttribute("authorname", node.SelectSingleNode("author").InnerText);
					string txt = node.SelectSingleNode("text").InnerText;
					itemnode.InnerText = txt.Substring(0, Math.Min(txt.Length, 50)) + "...";	// can contain ' and " etc
					commentsnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)
					xmlX.AddElemAttr(xmldom, commentsnode, "nodata", "", "prompt", "no images");
				profile.AddNodetoProfile("profile", commentsnode, true);
			} else {
				XmlNode blognode = xmldom.SelectSingleNode("//blog");
				if (blognode != null) {
					commentsnode = xmlX.AddElem(xmldom, blognode, "comments", "");
					xmlX.AddElemAttr(xmldom, commentsnode, "nodata", "", "prompt", "no comments");
					profile.AddNodetoProfile("profile", commentsnode, true);
				}
			}
		}
		// add images to profile items - for image list interface
		private static void addBlogImageXml(XmlDocument xmldom, profileX profile) {
			profile.RemoveNodefromProfile("images");
			XmlNode imagesnode = xmldom.SelectSingleNode("//blog/images");
			if (imagesnode != null) {
				XmlNodeList nodeList = imagesnode.SelectNodes("image");
				foreach (XmlNode node in nodeList) {
					XmlElement itemnode = xmlX.AddElemAttrNode(xmldom, node, "item", 1);
					itemnode.SetAttribute("authorname", node.SelectSingleNode("author").InnerText);
					string txt = node.SelectSingleNode("text").InnerText;
					itemnode.InnerText = txt.Substring(0, Math.Min(txt.Length, 50)) + "...";	// can contain ' and " etc
					imagesnode.AppendChild(itemnode);
				}
				if (nodeList.Count == 0)
					xmlX.AddElemAttr(xmldom, imagesnode, "nodata", "", "prompt", "no images");
				profile.AddNodetoProfile("profile", imagesnode, true);
			} else {
				XmlNode blognode = xmldom.SelectSingleNode("//blog");
				if (blognode != null) {
					imagesnode = xmlX.AddElem(xmldom, blognode, "images", "");
					xmlX.AddElemAttr(xmldom, imagesnode, "nodata", "", "prompt", "no images");
					profile.AddNodetoProfile("profile", imagesnode, true);
				}
			}
		}
		// add blog comment to profile fields - to edit/del single comment
		private static void getCommentXml(XmlDocument xmldom, profileX profile) {
			XmlElement blognode = (XmlElement) xmldom.SelectSingleNode("//comment");
			XmlNode textnode;
			string thisid = "", thistext = "", thistitle = "";
			if (blognode != null) {
				thisid = blognode.GetAttribute("id");
				textnode = blognode.SelectSingleNode("text");
				thistext = (textnode != null)? textnode.InnerXml : "";
				textnode = blognode.SelectSingleNode("title");
				thistitle = (textnode != null)? textnode.InnerXml : "";
			}
			profile.AddProfileValue("cid", thisid);
			profile.AddProfileValue("Comment_Title", thistitle);
			profile.AddProfileValue("Comment_Text", thistext);
		}
		// add blog image to profile fields - to edit/del single image
		private static void getBlogImageXml(XmlDocument xmldom, profileX profile) {
			XmlElement blognode = (XmlElement)xmldom.SelectSingleNode("//image");
			XmlNode textnode;
			string thisid = "", thistext = "", thistitle = "";
			if (blognode != null) {
				thisid = blognode.GetAttribute("id");
				textnode = blognode.SelectSingleNode("text");
				thistext = (textnode != null) ? textnode.InnerXml : "";
				textnode = blognode.SelectSingleNode("title");
				thistitle = (textnode != null) ? textnode.InnerXml : "";
			}
			profile.AddProfileValue("iid", thisid);
			profile.AddProfileValue("Image_Title", thistitle);
			profile.AddProfileValue("Image_Text", thistext);
		}
		// add blog image ID to profile field - return id after adding
		private static void getBlogImageID(XmlDocument xmldom, profileX profile) {
			XmlElement imgnode = (XmlElement)xmldom.SelectSingleNode("//blog/images/image[last()]");
			string thisid = (imgnode == null)? "" : imgnode.GetAttribute("id");
			profile.AddProfileValue("iid", thisid);
		}
		#endregion

		#region BlogSpace methods
		// add blogspace to profile items
		private static void getBlogspaceListXml(XmlDocument xmldom, profileX profile, contentX content) {
			XmlNode blogsnode = xmldom.SelectSingleNode("//blogspaces");
			XmlNode itemsnode = content.Xml.SelectSingleNode("//page/section/grpform/items");
			if (blogsnode != null) {
				XmlNodeList nodeList = blogsnode.SelectNodes("//blogspace");
				foreach (XmlNode node in nodeList) {
					//XmlElement nodeElem = (XmlElement) node;
					XmlElement itemel = xmlX.AddElemAttrNode(content.Xml, node, "item", 1);
					if (itemel.GetAttribute("type") == "")
						itemel.SetAttribute("type", "-");
					itemel.InnerText = node.InnerText;
					itemsnode.AppendChild(itemel);
				}
				if (nodeList.Count == 0)	// add nodata element when no results
					xmlX.AddElemAttr(content.Xml, itemsnode, "nodata", "", "prompt", "no thoughspaces");
			}
		}
		// add blogspace to profile fields
		private static void getBlogspaceXml(XmlDocument xmldom, profileX profile) {
			XmlElement spaceel = (XmlElement) xmldom.SelectSingleNode("//blogspace");
			if (spaceel != null) {
				profile.AddProfileValue("SpaceName", spaceel.GetAttribute("name"));
				profile.AddProfileValue("SpaceType", spaceel.GetAttribute("type"));
				profile.AddProfileValue("Admin", spaceel.GetAttribute("admin"));
				profile.AddProfileValue("Title", spaceel.SelectSingleNode("title").InnerText);
				profile.AddProfileValue("Text", spaceel.SelectSingleNode("text").InnerText);
				XmlNode adminnode = spaceel.SelectSingleNode(String.Concat("users/user[@name='", spaceel.GetAttribute("admin"), "']"));
				profile.AddProfileValue("AdminName", String.Concat(adminnode.SelectSingleNode("firstname").InnerText, " ", adminnode.SelectSingleNode("surname").InnerText));
				// get blog node (if exists)
				XmlNode blognode = spaceel.SelectSingleNode("blog");
				profile.AddProfileValue("BlogTitle", (blognode != null)? blognode.SelectSingleNode("title").InnerText : "");
				profile.AddProfileValue("BlogText", (blognode != null)? blognode.SelectSingleNode("bloghtml").InnerText : "");
				XmlNode imgnode = spaceel.SelectSingleNode("blog/image");
				profile.AddProfileValue("ImageName", (imgnode != null)? imgnode.InnerText : "");
				
				profile.AddProfileValue("id", spaceel.GetAttribute("name"));	// used in blogspaceSet when setting space
			}
			addTopicsListXml(xmldom, profile);
			profile.AddProfileValue("Topics", "0");	// try
		}
		// add blogspace archive to profile fields
		private static void getBlogspaceArchive(XmlDocument xmldom, profileX profile) {
			XmlElement archelem = (XmlElement) xmldom.SelectSingleNode("//archives");
			profile.AddProfileValue("ArchiveType", archelem.GetAttribute("type"));
		}
		/// <summary>
		/// Method description
		/// </summary>
		private static void blogspaceReset(profileX profile) {
			profile.ClearProfileValue("Title");
			profile.ClearProfileValue("Text");
		}
		/// <summary>
		/// Method description
		/// </summary>
		private static void blogspaceSet(profileX profile) {
			profile.AddProfileValue("BlogSpaces", profile.GetProfileValue("id"));
		}
		// add blogspaces to a drop-down fld on the content page
		private static void getBlogspaceDropXml(XmlDocument xmldom, profileX profile, contentX content) {
			XmlNode spacesnode = xmldom.SelectSingleNode("//blogspaces");
			if (spacesnode != null) {
				profile.ClearSubobjfromFld("Spaces");
				profile.AddSubobjtoFld("Spaces", "Select thoughtspace...", "0");
				XmlElement nodeElem;
				foreach (XmlNode node in spacesnode.SelectNodes("blogspace")) {
					nodeElem = (XmlElement) node;
					profile.AddSubobjtoFld("Spaces", nodeElem.InnerText, nodeElem.GetAttribute("name"));
				}
			}
		}
		#endregion

		#region Contact methods
		private static void sendContact(profileX profile, string which) {
			string message = "";
			string subject = String.Concat("Thoughtspace Contact: ", which);
			switch (which) {
				case "Password":	message = String.Concat("Name: ", profile.GetProfileValue("MyUsername"), "\nEmail: ", profile.GetProfileValue("MyEmail"));	break;
				case "General":		message = String.Concat("Name: ", profile.GetProfileValue("Author"), "\nEmail: ", profile.GetProfileValue("Email"), "\nMessage: ", profile.GetProfileValue("Text"));	break;
			}
			sendEmail(subject, message);
		}
		private static void sendEmail(string subject, string message) {
			string fromAddr = "admin@thoughtspace.co.za";
			string toAddr = ConfigurationManager.AppSettings["contact_email"];
			try {
				SmtpClient smtp = new SmtpClient();
				smtp.Host = ConfigurationManager.AppSettings["contact_server"];
				smtp.Send(toAddr, fromAddr, subject, message);
			}
			catch(System.Exception e) {
				throw(new exceptionX("error_send", "Could not send contact email", e));
			}
		}
		#endregion
	}
}
		
